package com.rtsapp.server.simulator.socket;

import com.rtsapp.server.logger.Logger;
import com.rtsapp.server.logger.LoggerFactory;
import com.rtsapp.server.network.protocol.crypto.client.ClientRSAHandshakeKey;
import com.rtsapp.server.simulator.IDataReceive;
import com.rtsapp.server.simulator.ITcpSocket;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;

import java.net.InetSocketAddress;
import java.net.SocketAddress;

/**
 * Created by admin on 16-6-18.
 */
public class SimulatorNettySocket implements ITcpSocket {

    private static final Logger LOG = LoggerFactory.getLogger(SimulatorNettySocket.class);

    private final String ip;
    private final int port;
    private final SocketAddress remotePeer;
    private final EventLoopGroup eventLoop;
    private final ClientRSAHandshakeKey handshakeKey;

    private IDataReceive receive;
    private Channel channel;

    public SimulatorNettySocket(String ip, int port, ClientRSAHandshakeKey handshakeKey ) {
        this.ip = ip;
        this.port = port;
        this.remotePeer = new InetSocketAddress(ip, port);
        this.eventLoop = new NioEventLoopGroup(1);
        this.handshakeKey = handshakeKey;
    }


    @Override
    public void setReceive(IDataReceive receive) {
        this.receive = receive;
    }


    @Override
    public void connect() throws Exception {

        Bootstrap b = new Bootstrap();

        SimulatorChannelInitializer initializer = null;

        if( handshakeKey == null ){
            initializer = new SimulatorChannelInitializer(receive);
        }else{
            initializer = new CryptoSimulatorChannelInitialzer( receive, handshakeKey );
        }

        b.group(eventLoop)
                .channel(NioSocketChannel.class)
                .handler( initializer );

        ChannelFuture channelFuture = b.connect(remotePeer);
        channelFuture.sync();

        channel = channelFuture.channel();

        System.out.println("\nSuccessfully connected to the " + ip + ":" + port);
    }

    @Override
    public void close() {
        channel.close();
    }

    @Override
    public void send(byte[] bytes, int length) {

        ByteBuf buf = Unpooled.copiedBuffer( bytes, 0, length );

        channel.writeAndFlush( buf );

    }


}
